﻿using DGZImp.BasProject.DomainModels;
using DGZImp.Core.DbSqlSugar;
using DGZImp.Core.EFDbContext;
using DGZImp.Core.Exceptions;
using DGZImp.Core.Extensions;
using DGZImp.Core.Services;
using DGZImp.Core.Utilities.Response;
using DGZImp.MdsProject.Devices;
using DGZImp.MdsProject.Devices.Base;
using DGZImp.MdsProject.Devices.Entities;
using DGZImp.MdsProject.Devices.Models;
using DGZImp.MdsProject.DomainModels;
using DGZImp.MdsProject.Helper;
using DGZImp.MdsProject.IServices;
using DGZImp.MdsProject.Models;
using DGZImp.WmsProject.IServices;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Nomad.Iot.Profinet.Siemens;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace DGZImp.MdsProject.Services
{
    public class MdsCustomizeService : IMdsCustomizeService, IDependency
    {
        public ISqlSugarClient Db = AutofacContainerModule.GetService<ServiceDbContext>().SqlSugarClient;
        public MdsInit mdsInit = AutofacContainerModule.GetService<MdsInit>();
        public Mds_LogisticTaskService taskService { get; set; }

        /// <summary>
        /// 镭神AGV任务回调
        /// </summary>
        public async Task<string> LsAgvTaskSync(LaAgvTaskSyncDto data)
        {
            var res = new
            {
                ackCode = data.reqCode > 0 ? data.reqCode : data.rescode,
            };

            SysLogger.LogDebug("接收到AGV回调数据：" + JsonConvert.SerializeObject(data));
            if (data.taskname.IsNullOrEmpty())
            {
                var msg = "AGV回调数据任务编号不能为空";
                SysLogger.LogError(msg);
                throw new AppException(msg);
            }
            var taskNameArr = data.taskname.Split('-');
            var taskNo = 0;
            try
            {
                if (taskNameArr[0] == "ordering") taskNo = 0;
                else taskNo = Convert.ToInt32(taskNameArr[0]);
            }
            catch (Exception)
            {
                var msg = $"AGV回调数据任务编号{data.taskname}格式不正确";
                SysLogger.LogError(msg);
                throw new AppException(msg);
            }

            var taskDetail = await taskService.GetTaskDetailByNo(taskNo);
            if (taskDetail == null)
            {
                var msg = $"AGV回调数据任务编号{data.taskname}不存在";
                SysLogger.LogWarning(msg);
                // return JsonConvert.SerializeObject(res);
            }

            var agvId = data.deviceid ?? data.agvinfo;
            var agv = mdsInit.devices.Where(x => x.Device is LsAgv)
                .Where(x => ((LsAgv)x.Device).Data.AgvIp == agvId).FirstOrDefault();
            if (agv == null)
            {
                var msg = $"收到镭神AGV控制请求，但是设备{data.deviceid ?? data.agvinfo}不存在";
                SysLogger.LogError(msg);
                throw new AppException(msg);
            }

            if (data.reqtype == LsAgvReqTypeEnum.任务正在处理 && taskDetail != null)  // 任务开始执行
            {
                //任务正在执行时，依据AGV调度系统实际车来更新任务执行的小车信息
                await Db.DoUpdateAsync<Mds_LogisticTaskDetail>(new
                {
                    MachineId = agv.MachineId
                }, x => x.LogisticTaskDetailId == taskDetail.LogisticTaskDetailId);
            }
            else if (data.reqtype == LsAgvReqTypeEnum.取货完成 && taskDetail != null)
            {
                //取消此逻辑，因取货完成时 没有点控的情况下，下发后续设备 执行动作 可能会造成事故

                //取货完成时，检查取货点 是否配置 待命确认点，若有则 不下发后续设备 取货完成信号
                //取消取货完成
                //if (taskDetail.TaskStatus == (int)LogisticTaskStatus.进行中)
                //{
                //    try
                //    {
                //        await LsAgvHelper.HandleTaskComplete(taskDetail, data.reqtype, data.data);
                //    }
                //    catch (Exception e)
                //    {
                //        var msg = $"AGV任务 {taskDetail?.TaskNo}/{data.reqtype} 后逻辑处理时发生异常.";
                //        SysLogger.LogError(e, msg);
                //        await taskService.AddTaskLog(taskDetail.LogisticTaskId, LogMessageType.错误, msg + e.Message);
                //    }
                //}
            }
            else if (data.reqtype == LsAgvReqTypeEnum.任务完成 && taskDetail != null)  // 任务完成
            {
                if (taskDetail.TaskStatus == (int)LogisticTaskStatus.进行中)
                    await taskService.FinishLogisticDetailTask(taskDetail.LogisticTaskDetailId, null);
                //AGV任务完成后的一些特殊逻辑调用, 判断当前位置是否有 配置确认 点位
                try
                {
                    await LsAgvHelper.HandleTaskComplete(taskDetail, data.reqtype, data.data);
                }
                catch (Exception e)
                {
                    var msg = $"AGV任务 {taskDetail?.TaskNo}/{data.reqtype} 后逻辑处理时发生异常.";
                    SysLogger.LogError(e, msg);
                    await taskService.AddTaskLog(taskDetail.LogisticTaskId, LogMessageType.错误, msg + e.Message);
                }
            }
            else if (data.reqtype == LsAgvReqTypeEnum.任务异常 && taskDetail != null)  // 任务取消
            {
                taskDetail.TaskStatus = (int)LogisticTaskStatus.已取消;
                await taskService.UpdateLogisticTask(taskDetail);
            }
            else if (data.operation_type == LsAgvControlTypeEnum.点控制响应)
            {
                if (data.status == -1) // 可以忽略的点请求，直接继续
                {
                    ((LsAgv)agv.Device).SendContinueTaskAsync(data.operation_type).Wait();
                    return JsonConvert.SerializeObject(res);
                }
                // 节点控制请求应答
                var check = LsAgvHelper.HandleAgvControl(agv, data.taskname, data.data, taskDetail.LogisticTaskId,
                    (LsAgvOperationEnum)data.status, taskDetail.LogisticTaskDetailId);
                if (check)
                {
                    ((LsAgv)agv.Device).SendContinueTaskAsync(data.operation_type).Wait();
                }
            }
            else if (data.operation_type == LsAgvControlTypeEnum.路径控制响应)  // 路径控制请求应答
            {
                var check = LsAgvHelper.HandleAgvControl(agv, data.taskname, data.data, taskDetail.LogisticTaskId);
                if (check)
                {
                    ((LsAgv)agv.Device).SendContinueTaskAsync(data.operation_type).Wait();
                }
            }
            return JsonConvert.SerializeObject(res);
        }


        /// <summary>
        /// SCADA获取设备任务
        /// </summary>
        public async Task<ResScadaGetDeviceTask> ScadaGetDeviceTask(ReqScadaGetDeviceTask data)
        {
            var task = await Db.Set<Mds_ProductionTask>()
                .LeftJoin<Bas_Machine>((a, b) => a.MachineId == b.MachineId)
                .LeftJoin<Aps_Mo>((a, b, c) => a.WorkOrder == c.MoCode)
                .Where((a, b) => b.MachineCode == data.DeviceCode)
                .Where((a, b) => a.TaskStatus == (int)ProductionTaskStatus.准备中 || a.TaskStatus == (int)ProductionTaskStatus.进行中)
                .Select((a, b, c) => new ResScadaGetDeviceTask
                {
                    DeviceCode = b.MachineCode,
                    TaskCode = SqlFunc.ToString(a.ProductionTaskId),
                    ProductId = SqlFunc.ToString(c.MaterialId),
                    ProductName = c.ProductsCode,
                    ProductQty = c.Qty,
                    MaterialLot = c.LotNo,
                })
                .FirstAsync();
            if (task == null)
                task = new ResScadaGetDeviceTask
                {
                    DeviceCode = data.DeviceCode,
                };
            return task;
        }

        public async Task<bool> SendDeviceEvent(ReqSendDeviceEvent data)
        {
            SysLogger.LogDebug("接收到SCADA发送设备事件：" + JsonConvert.SerializeObject(data));
            //取货完成 or 放货完成
            if (data.EventCode == "2" || data.EventCode == "3")
            {
                //此时设备回调的数据为生产设备信息，需要依次转换为AGV设备
                //SCADA回调是传值为 当前生产设备ID，需要依据生产设备ID转换为AGV的信息
                //{"DeviceCode":"D-040113","EventCode":"2","TaskCode":"1816249786813440"}
                await LsAgvHelper.HandleScadaEvent(data);
            }
            else if (data.EventCode == "1")
            {
                //依据设备号、任务号产生当前设备下架任务
            }
            else if (data.EventCode == "9")
            {

            }
            else
            { }
            return true;
        }
    }

    public class LaAgvTaskSyncDto
    {
        public int code { get; set; }
        public int type { get; set; }
        public string agvinfo { get; set; }
        public string deviceid { get; set; }
        public string taskname { get; set; }
        public int rescode { get; set; }
        public int reqCode { get; set; }

        /// <summary>
        /// 0:任务生成 1:任务正在处理 2:取货完成 3:任务完成 4:任务异常
        /// </summary>
        public LsAgvReqTypeEnum reqtype { get; set; }
        public LsAgvControlTypeEnum operation_type { get; set; }
        public int status { get; set; }
        public List<string> data { get; set; }
    }

    public class ReqScadaGetDeviceTask
    {
        public string DeviceCode { get; set; }
    }

    public class ResScadaGetDeviceTask
    {
        public string DeviceCode { get; set; }
        public string TaskCode { get; set; }
        public string ProductId { get; set; }
        public string ProductName { get; set; }
        public decimal? ProductQty { get; set; }
        public string MaterialLot { get; set; }
    }

    public class ReqSendDeviceEvent
    {
        public string DeviceCode { get; set; }

        /// <summary>
        /// 事件代码
        /// 1.需要下料 2.取料结束 3.放料结束 9.生产任务完成
        /// </summary>
        public string EventCode { get; set; }

        public string TaskCode { get; set; }
    }
}
